package com.hhwy.framework.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.hhwy.framework.common.Constants;

/**
 * 创建日期:2015年3月28日
 * Title:对插件配置文件（plugin-config.xml）中的扫描范围进行管理
 * Description：对本文件的详细描述，原则上不能少于50字
 * @author liuh
 * @mender：（文件的修改者，文件创建者之外的人）
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
public class PluginScanHelper {
	
	public static final Logger log = LoggerFactory.getLogger(PluginScanHelper.class);
	/**
	 * 插件配置文件路径
	 */
	public static final String PLUGIN_CONFIG_PATH = IoTools.getABSPATH()
			+ Constants.PLUGIN_DIR + "/plugin-config.xml";
	
	/**
	 * 功能:添加需要扫描的包 
	 * 作者: liuh 
	 * 创建日期:2015年3月28日 
	 * 修改者: mender 
	 * 修改日期: modifydate
	 * @param packages
	 * @return
	 */
	public static boolean addPackage(final String packages) {
		return operator(new Callback() {
			@Override
			public void attributeOperator(Attribute attribute) {
				String attr = attribute.getValue();
				String[] attrArray = StringUtils.split(attr, " , ");
				List<?> attrList = CollectionUtils.arrayToList(attrArray);
				
				String[] packageArray = StringUtils.split(packages, " , ");
				for(String packageName : packageArray){
					if(!attrList.contains(packageName)){
						attr = attr + "," + packageName;
					}
				}
				attribute.setValue(attr);
			}
		});
	}

	/**
	 * 功能:删除扫描的包 
	 * 作者: liuh 
	 * 创建日期:2015年3月28日 
	 * 修改者: mender 
	 * 修改日期: modifydate
	 * @param packages
	 * @return
	 */
	public static boolean deletePackage(final String packages) {
		return operator(new Callback() {
			@Override
			public void attributeOperator(Attribute attribute) {
				String attr = attribute.getValue();
				String[] attrArray = StringUtils.split(attr, " , ");
				@SuppressWarnings("unchecked")
				List<String> ps = new ArrayList<>(CollectionUtils.arrayToList(attrArray));
				
				String[] packageArray = StringUtils.split(packages, " , ");
				for(String packageName : packageArray){
					if (ps.contains(packageName)) {
						ps.remove(packageName);
					}
				}
				attribute.setValue(StringUtils.join(ps.toArray(), ","));
			}
		});
	}

	@SuppressWarnings("unchecked")
	private static boolean operator(Callback callback) {
		SAXReader reader = new SAXReader();
		File pluginxml = new File(PLUGIN_CONFIG_PATH);
		if(!pluginxml.exists()){
			log.error("插件配置文件plugin-config.xml不存在！");
			return false;
		}
		try {
			Document document = reader.read(pluginxml);
			String encoding = document.getXMLEncoding();
			Element node = document.getRootElement();
			List<Element> elements = node.elements();
			for (Element element : elements) {
				if ("java.util.HashMap".equals(element.attributeValue("class"))) {
					Element entry = element;
					List<Element> list= null;
					while(!(list = entry.elements()).isEmpty()){
						entry = list.get(0);
					}
					Attribute attribute = entry.attribute("value");
					entry.remove(attribute);
					callback.attributeOperator(attribute);
					entry.add(attribute);
				} else if ("component-scan".equals(element.getName())) {
					Attribute attribute = element.attribute("base-package");
					element.remove(attribute);
					callback.attributeOperator(attribute);
					element.add(attribute);
				}
			}
			writer(document, PLUGIN_CONFIG_PATH, encoding);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private static void writer(Document document, String fileUrl,
			String encoding) throws Exception {
		// 排版缩进的格式
		OutputFormat format = OutputFormat.createPrettyPrint();
		// 设置编码
		format.setEncoding(encoding);
		// 创建XMLWriter对象,指定了写出文件及编码格式
		XMLWriter writer = new XMLWriter(new OutputStreamWriter(
				new FileOutputStream(new File(fileUrl)), encoding), format);
		// 写入
		writer.write(document);
		// 立即写入
		writer.flush();
		// 关闭操作
		writer.close();
	}
	
	public interface Callback {
		public void attributeOperator(Attribute attrs);
	}
}
